/* *****************************************************************************************************************************
 * (c) J@mBeL.net 2010-2015
 * Author: John Ambeliotis
 * Created: 24 Apr. 2010
 *
 * License:
 *  This file is part of Project jaNET.

    Project jaNET is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Project jaNET is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Project jaNET. If not, see <http://www.gnu.org/licenses/>. */

using System;
using System.Text;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Net.Mail;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Xml;
using System.Collections;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Diagnostics;

namespace libJanet
{
    class Net
    {
        internal class Mail
        {
            internal bool Send(string sFrom, string sTo, string sSubject, string sBody)
            {
                if (!Methods.hasInternetConnection())
                    return false;

                try
                {
                    SmtpSettings smtpSettings = new SmtpSettings();

                    if (smtpSettings.Host != null)
                    {
                        MailMessage mail = new MailMessage();

                        mail.From = new MailAddress(sFrom);
                        mail.To.Add(sTo);
                        mail.Subject = sSubject;
                        mail.Body = sBody;

                        SmtpClient smtpClient = new SmtpClient(smtpSettings.Host);
                        smtpClient.Port = smtpSettings.Port;
                        smtpClient.Credentials = new NetworkCredential(smtpSettings.Username, smtpSettings.Password);
                        smtpClient.EnableSsl = smtpSettings.SSL;
                        if (smtpClient.EnableSsl)
                            ServicePointManager.ServerCertificateValidationCallback =
                                delegate(object s, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
                                { return true; };
                        smtpClient.Send(mail);
                        return true;
                    }
                    return false; // Settings not found
                }
                catch
                {
                    return false;
                }
            }

            internal int Pop3Check()
            {
                try
                {
                    Pop3Settings pop3Settings = new Pop3Settings();

                    Pop3 obj = new Pop3();
                    obj.Connect(pop3Settings.Host, pop3Settings.Username, pop3Settings.Password, pop3Settings.Port);
                    string KeyWord = Queries.Xml.AppConfigQuery("jaNET/System/Comm/MailKeyword").Item(0).InnerText;

                    foreach (Pop3Message msg in obj.List())
                    {
                        Pop3Message msg2 = obj.Retrieve(msg);
                        /*Console.WriteLine("Message {0}: {1}",
                            msg2.number, msg2.message);*/
                        if (msg2.message.Contains("<" + KeyWord + ">"))
                        {
                            //If a command found to mail subject
                            Match Command = Regex.Match(msg2.message.Replace("\r\n", " "), @"(<" + KeyWord + ">)(.*?)(?=</" + KeyWord + ">)");
                            Parser.Parse(Command.ToString().ToLower().Replace("<" + KeyWord + ">", string.Empty));
                            obj.Delete(msg2);
                        }
                        else
                        {
                            //For Future Use
                            /*Match From = Regex.Match(msg2.message, @"(?<=From: )(.*?)(?= <)");
                            Match Subject = Regex.Match(msg2.message, @"(?<=Subject: )(.*?)(?=\\r\\nDate: )"); //(?<=Subject:</B> )(.*?)(?=</)");
                            MailList.Add("From " + From.ToString() + ", Subject " + Subject.ToString());*/
                            //From pattern (?<=From: \\\")(.*?)(?=\\\")
                            //Subject pattern (?<=Subject: )(.*?)(?=\\r)
                        }
                    }
                    obj.Disconnect();
                    return obj.List().Count;
                }
                catch
                {
                    return 0;
                }
            }

            internal string GmailCheck(bool CountOnly)
            {
                try
                {
                    //Change SSL checks so that all checks pass
                    ServicePointManager.ServerCertificateValidationCallback =
                        new RemoteCertificateValidationCallback(
                            delegate
                            { return true; }
                        );

                    WebRequest webGmailRequest = WebRequest.Create(@"https://mail.google.com/mail/feed/atom");
                    webGmailRequest.PreAuthenticate = true;

                    GmailSettings gmailSettings = new GmailSettings();
                    string gmailUser = gmailSettings.Username;
                    string gmailPassword = gmailSettings.Password;
                    NetworkCredential loginCredentials = new NetworkCredential(gmailUser, gmailPassword);
                    webGmailRequest.Credentials = loginCredentials;

                    WebResponse webGmailResponse = webGmailRequest.GetResponse();
                    Stream strmUnreadMailInfo = webGmailResponse.GetResponseStream();

                    StringBuilder sbUnreadMailInfo = new StringBuilder(); byte[] buffer = new byte[8192]; int byteCount = 0;

                    while ((byteCount = strmUnreadMailInfo.Read(buffer, 0, buffer.Length)) > 0)
                        sbUnreadMailInfo.Append(Encoding.ASCII.GetString(buffer, 0, byteCount));

                    XmlDocument UnreadMailXmlDoc = new XmlDocument();
                    UnreadMailXmlDoc.LoadXml(sbUnreadMailInfo.ToString());
                    XmlNodeList UnreadMailEntries = UnreadMailXmlDoc.GetElementsByTagName("entry");

                    if (!CountOnly)
                    {
                        string output = string.Empty;
                        for (int i = 0; i < UnreadMailEntries.Count; ++i)
                        {
                            output += ("Message " + (i + 1) + ".") + "\r\n";
                            output += ("Subject: " + (UnreadMailEntries[i]["title"]).InnerText) + "\r\n";
                            output += ("From: " + (UnreadMailEntries[i]["author"])["name"].InnerText + " <" + (UnreadMailEntries[i]["author"])["email"].InnerText + ">") + "\r\n";
                            output += ("Date: " + DateTime.Parse((UnreadMailEntries[i]["modified"]).InnerText)) + "\r\n";
                        }
                        output += "Total: " + UnreadMailEntries.Count;
                        return output;
                    }
                    return UnreadMailEntries.Count.ToString();
                }
                catch
                {
                    return "0";
                }
            }

            public class Pop3Exception : System.ApplicationException
            {
                public Pop3Exception(string str)
                    : base(str)
                {
                }
            }
            public class Pop3Message
            {
                public long number;
                public long bytes;
                public bool retrieved;
                public string message;
            }
            public class Pop3 : System.Net.Sockets.TcpClient
            {
                public void Connect(string server, string username, string password, int port)
                {
                    try
                    {
                        string message;
                        string response;

                        Connect(server, port);
                        response = Response();
                        if (response == string.Empty)
                        {
                            throw new Pop3Exception(response);
                        }
                        if (response.Substring(0, 3) != "+OK")
                        {
                            throw new Pop3Exception(response);
                        }

                        message = "USER " + username + "\r\n";
                        Write(message);
                        response = Response();
                        if (response.Substring(0, 3) != "+OK")
                        {
                            throw new Pop3Exception(response);
                        }

                        message = "PASS " + password + "\r\n";
                        Write(message);
                        response = Response();
                        if (response.Substring(0, 3) != "+OK")
                        {
                            throw new Pop3Exception(response);
                        }
                    }
                    catch (Exception e)
                    {
                        //Console.WriteLine(e.Message);
                        Debug.Print(e.Message);
                    }
                }
                public void Disconnect()
                {
                    try
                    {
                        string message;
                        string response;
                        message = "QUIT\r\n";
                        Write(message);
                        response = Response();
                        if (response.Substring(0, 3) != "+OK")
                        {
                            throw new Pop3Exception(response);
                        }
                    }
                    catch (Exception e)
                    {
                        //Console.WriteLine(e.Message);
                        Debug.Print(e.Message);
                    }
                }
                public ArrayList List()
                {
                    try
                    {
                        string message;
                        string response;

                        ArrayList retval = new ArrayList();
                        message = "LIST\r\n";
                        Write(message);
                        response = Response();
                        if (response.Substring(0, 3) != "+OK")
                        {
                            throw new Pop3Exception(response);
                        }

                        while (true)
                        {
                            response = Response();
                            if (response == ".\r\n")
                            {
                                return retval;
                            }
                            else
                            {
                                Pop3Message msg = new Pop3Message();
                                char[] seps = { ' ' };
                                string[] values = response.Split(seps);
                                msg.number = Int32.Parse(values[0]);
                                msg.bytes = Int32.Parse(values[1]);
                                msg.retrieved = false;
                                retval.Add(msg);
                                continue;
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        //Console.WriteLine(e.Message);
                        Debug.Print(e.Message);
                        return null;
                    }
                }
                public Pop3Message Retrieve(Pop3Message rhs)
                {
                    try
                    {
                        string message;
                        string response;

                        Pop3Message msg = new Pop3Message();
                        msg.bytes = rhs.bytes;
                        msg.number = rhs.number;

                        message = "RETR " + rhs.number + "\r\n";
                        Write(message);
                        response = Response();
                        if (response.Substring(0, 3) != "+OK")
                        {
                            throw new Pop3Exception(response);
                        }

                        msg.retrieved = true;
                        while (true)
                        {
                            response = Response();
                            if (response == ".\r\n")
                            {
                                break;
                            }
                            else
                            {
                                msg.message += response;
                            }
                        }
                        return msg;
                    }
                    catch (Exception e)
                    {
                        //Console.WriteLine(e.Message);
                        Debug.Print(e.Message);
                        return null;
                    }
                }
                public void Delete(Pop3Message rhs)
                {
                    try
                    {
                        string message;
                        string response;

                        message = "DELE " + rhs.number + "\r\n";
                        Write(message);
                        response = Response();
                        if (response.Substring(0, 3) != "+OK")
                        {
                            throw new Pop3Exception(response);
                        }
                    }
                    catch (Exception e)
                    {
                        //Console.WriteLine(e.Message);
                        Debug.Print(e.Message);
                    }
                }
                private void Write(string message)
                {
                    try
                    {
                        ASCIIEncoding en = new ASCIIEncoding();

                        byte[] WriteBuffer = new byte[1024];
                        WriteBuffer = en.GetBytes(message);

                        NetworkStream stream = GetStream();
                        stream.Write(WriteBuffer, 0, WriteBuffer.Length);

                        //Debug.WriteLine("WRITE:" + message);
                    }
                    catch (Exception e)
                    {
                        //Console.WriteLine(e.Message);
                        Debug.Print(e.Message);
                    }
                }
                private string Response()
                {
                    try
                    {
                        ASCIIEncoding enc = new ASCIIEncoding();
                        byte[] serverbuff = new Byte[1024];
                        NetworkStream stream = GetStream();
                        int count = 0;
                        while (true)
                        {
                            byte[] buff = new Byte[2];
                            int bytes = stream.Read(buff, 0, 1);
                            if (bytes == 1)
                            {
                                serverbuff[count] = buff[0];
                                count++;
                                if (buff[0] == '\n')
                                {
                                    break;
                                }
                            }
                            else
                            {
                                break;
                            };
                        };
                        string retval = enc.GetString(serverbuff, 0, count);
                        //Debug.WriteLine("READ:" + retval);
                        return retval;
                    }
                    catch (Exception e)
                    {
                        return e.Message;
                    }
                }
            }

            internal class SmtpSettings
            {
                //Gmail settings "smtp.gmail.com"
                //Gmail port 587
                //Gmail SSL true

                internal string Host { get; private set; }
                internal string Username { get; private set; }
                internal string Password { get; private set; }
                internal int Port { get; private set; }
                internal bool SSL { get; private set; }

                internal SmtpSettings()
                {
                    IList<String> smtpSettings = new FileSystem.Settings().LoadSettings(".smtpsettings");

                    if (smtpSettings != null)
                    {
                        Host = smtpSettings[0];
                        Username = smtpSettings[1];
                        Password = smtpSettings[2];
                        Port = Convert.ToInt32(smtpSettings[3]);
                        SSL = Convert.ToBoolean(smtpSettings[4]);
                    }
                }
            }

            internal class Pop3Settings
            {
                internal string Host { get; private set; }
                internal string Username { get; private set; }
                internal string Password { get; private set; }
                internal int Port { get; private set; }
                internal bool SSL { get; private set; }

                internal Pop3Settings()
                {
                    IList<String> pop3Settings = new FileSystem.Settings().LoadSettings(".pop3settings");

                    if (pop3Settings != null)
                    {
                        Host = pop3Settings[0];
                        Username = pop3Settings[1];
                        Password = pop3Settings[2];
                        Port = Convert.ToInt32(pop3Settings[3]);
                        SSL = Convert.ToBoolean(pop3Settings[4]);
                    }
                }
            }

            internal class GmailSettings
            {
                internal string Username { get; private set; }
                internal string Password { get; private set; }

                internal GmailSettings()
                {
                    IList<String> gmailSettings = new FileSystem.Settings().LoadSettings(".gmailsettings");

                    if (gmailSettings != null)
                    {
                        Username = gmailSettings[0];
                        Password = gmailSettings[1];
                    }
                }
            }
        }
    }

    #region SMS
    class SMS
    {
        internal string Send(string smsTo, string smsMsg)
        {
            WebClient client = new WebClient();
            SmsSettings smsSettings = new SmsSettings();
            // Add a user agent header in case the requested URI contains a query.
            client.Headers.Add("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)");
            client.QueryString.Add("user", smsSettings.SmsUsername);
            client.QueryString.Add("password", smsSettings.SmsPassword);
            client.QueryString.Add("api_id", smsSettings.SmsAPI);
            client.QueryString.Add("to", smsTo);
            client.QueryString.Add("text", smsMsg);
            string baseurl = "http://api.clickatell.com/http/sendmsg";
            Stream data = client.OpenRead(baseurl);
            StreamReader reader = new StreamReader(data);
            string s = reader.ReadToEnd();
            data.Close();
            reader.Close();
            return (s);
        }

        internal class SmsSettings
        {
            internal string SmsUsername { get; private set; }
            internal string SmsPassword { get; private set; }
            internal string SmsAPI { get; private set; }

            internal SmsSettings()
            {
                IList<String> smsSettings = new FileSystem.Settings().LoadSettings(".smssettings");

                if (smsSettings != null)
                {
                    SmsAPI = smsSettings[0].ToString();
                    SmsUsername = smsSettings[1];
                    SmsPassword = smsSettings[2];
                }
            }
        }
    }
    #endregion
}